#include <cassert>
#include <cstdlib>
#include <iostream>
#include "curling/config.hpp"
#include "curling/opengl.hpp"
#include "curling/core.hpp"

int display_width = 0;
int display_height = 0;
curling::core* core = NULL;

/**
 *
 */
static void GLFWCALL callback_mouse_button( int button, int press )
{
  if (core == NULL) return;
}

/**
 *
 */
static void GLFWCALL callback_mouse_position( int x, int y )
{
  if (core == NULL) return;
}

/**
 *
 */
static void GLFWCALL callback_key( int key, int press )
{
  if (core == NULL) return;
  
  switch (press)
  {
  case GLFW_PRESS:
    core->key_down(glfwGetTime(), key, 0);
    break;
  
  case GLFW_RELEASE:
    core->key_up(glfwGetTime(), key, 0);
    break;
  
  default:
    assert(false);
    break;
  }
}

/**
 *
 */
static void GLFWCALL callback_character( int character, int press )
{
  if (core == NULL) return;
  
  switch (press)
  {
  case GLFW_PRESS:
    core->key_down(glfwGetTime(), 0, character);
    break;
  
  case GLFW_RELEASE:
    core->key_up(glfwGetTime(), 0, character);
    break;
  
  default:
    assert(false);
    break;
  }
}

/**
 *
 */
static void GLFWCALL callback_resize( int width, int height )
{
  display_width = width;
  display_height = height;
  glViewport(0, 0, width, height);
}

int main( int argc, char** argv )
{
  try {
    glfwInit();
    glfwOpenWindow(1024, 768, 0, 0, 0, 0, 24, 0, GLFW_WINDOW);
    glfwSetWindowTitle("Curling");
    
    glfwSwapInterval(1);
    
    glfwSetMouseButtonCallback(callback_mouse_button);
    glfwSetMousePosCallback(callback_mouse_position);
    glfwSetKeyCallback(callback_key);
    glfwSetCharCallback(callback_character);
    glfwSetWindowSizeCallback(callback_resize);
  
    glfwDisable(GLFW_KEY_REPEAT);
    glfwDisable(GLFW_MOUSE_CURSOR);
    
    core = new curling::core(1024, 768);
    
    double t0 = glfwGetTime();
    bool quit = false;
    while (!quit)
    {
      //calculate time and delta time since last frame
      double t1 = glfwGetTime();
      double dt = t1 - t0;
      t0 = t1;
      
      core->render(t1, dt);
      glfwSwapBuffers();
      
      GLenum opengl_error = glGetError();
      if (opengl_error != GL_NO_ERROR)
      {
        std::cerr << "OpenGL error: " << opengl_error << std::endl;
        #ifdef CURLING_PLATFORM_MACOSX
          std::cerr << gluErrorString(opengl_error) << std::endl;
          assert(false);
        #endif
      }
    
      quit = !glfwGetWindowParam(GLFW_OPENED);
      
      if (core->requests_quit())
      {
        quit = true;
      }
    }
    
    delete core;
    
    glfwCloseWindow();
    glfwTerminate();
  } catch (...) {
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}